﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;

namespace bypy
{
    class Program
    {
        static void Main(string[] args)
        {
            /*if (!File.Exists("Newtonsoft.Json.dll"))
            {
                File.WriteAllBytes("Newtonsoft.Json.dll", Properties.Resources.Newtonsoft_Json);
            }*/

            string filepath = @"C:\Windows\notepad.exe";
            string filename = DateTime.Now.ToString("yyyyMMddHHmmssfff_") + Path.GetFileName(filepath);
            if (args.Length != 0)
            {
                filepath = args[0];
                filename = Path.GetFileName(filepath);
            }
            if (!File.Exists(filepath))
            {
                Console.WriteLine("文件不存在！" + filepath);
                Console.ReadKey();
                return;
            }
            Token token = GetToken();
            if (!string.IsNullOrEmpty(token.error_msg))
            {
                Console.WriteLine("获取令牌失败！" + token.error_msg);
                Console.ReadKey();
                return;
            }
            Upload upload = DoUpload(token.access_token, filepath, filename);
            if (string.IsNullOrEmpty(upload.error_msg))
            {
                Console.WriteLine("上传成功！" + upload.path);
            }
            else
            {
                Console.WriteLine("上传失败！" + upload.error_msg);
            }
            Console.ReadKey();
        }
        static Token GetToken()
        {
            if (File.Exists("bypy.json"))
            {
                Console.Write("读取令牌缓存：");
                string json = File.ReadAllText("bypy.json");
                Token token = new Token(json);
                Console.WriteLine(token.access_token);
                Info info = GetInfo(token.access_token);
                return string.IsNullOrEmpty(info.quota) ? RefreshToken(token.access_token) : token;
            }
            else
            {
                return AuthToken();
            }
        }
        static Token AuthToken()
        {
            string url = "https://openapi.baidu.com/oauth/2.0/authorize?response_type=code&client_id=q8WE4EpCsau1oS0MplgMKNBn&redirect_uri=oob&scope=basic,netdisk";
            Console.WriteLine("打开百度登陆并授权。");
            Console.WriteLine(url);
            Process.Start("explorer.exe", url);
            Console.Write("输入复制的授权码回车：");
            string code = Console.ReadLine();
            Console.WriteLine("用授权码获取令牌");
            string url2 = "https://bypyoauth.herokuapp.com/auth?code=" + code + "&bypy_version=1.6.10&redirect_uri=oob";
            string resp = CUrl(url2);
            File.WriteAllText("bypy.json", FormatJson(resp));
            return new Token(resp);
        }
        static Token RefreshToken(string refresh_token)
        {
            Console.Write("刷新令牌：");
            string url = "https://bypyoauth.herokuapp.com/refresh?bypy_version=1.6.10&refresh_token=" + refresh_token;
            string resp = CUrl(url);
            Console.WriteLine(resp);
            File.WriteAllText("bypy.json", FormatJson(resp));
            return new Token(resp);
        }
        static Info GetInfo(string access_token)
        {
            Console.Write("获取用户配额：");
            string url = "https://pcs.baidu.com/rest/2.0/pcs/quota?method=info&access_token=" + access_token;
            string resp = CUrl(url);
            Console.WriteLine(resp);
            return new Info(resp);
        }
        static Upload DoUpload(string access_token, string filepath, string filename)
        {
            Console.WriteLine("准备上传：{0}", filepath);
            Console.WriteLine("保存文件：{0}", filename);
            string resp = BD.Upload(access_token, filepath, filename);
            return new Upload(resp);
            /*
            BD.SetSSl();
            string url = string.Format("https://c.pcs.baidu.com/rest/2.0/pcs/file?method=upload&access_token={0}&path={1}", token.access_token, filename);
            WebClient wc = new WebClient();
            byte[] bytes = wc.UploadFile(url, "POST", filepath);
            string resp = Encoding.UTF8.GetString(bytes);
            return new Upload(resp);
            */
        }
        static string CUrl(string url)
        {
            try
            {
                return new WebClient().DownloadString(url);
            }
            catch (WebException we)
            {
                if (we.Response != null)
                {
                    using (StreamReader stream = new StreamReader(we.Response.GetResponseStream(), Encoding.UTF8))
                    {
                        return stream.ReadToEnd();
                    }
                }
                else
                {
                    return string.Format("{\"error_msg\":\"{0}\"}", "Duang error");
                }
            }
            catch (Exception e)
            {
                return string.Format("{\"error_msg\":\"{0}\"}", e.Message);
            }
        }
        static string FormatJson(string json)
        {
            JsonSerializer serializer = new JsonSerializer();
            TextReader tr = new StringReader(json);
            JsonTextReader jtr = new JsonTextReader(tr);
            object obj = serializer.Deserialize(jtr);
            if (obj != null)
            {
                StringWriter textWriter = new StringWriter();
                JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)
                {
                    Formatting = Formatting.Indented,
                    Indentation = 4,
                    IndentChar = ' '
                };
                serializer.Serialize(jsonWriter, obj);
                return textWriter.ToString();
            }
            return json;
        }
    }
    internal class Token
    {
        public Token(string resp)
        {
            JObject obj = JObject.Parse(resp);
            this.error_msg = (string)obj.SelectToken("error_msg");
            this.access_token = (string)obj.SelectToken("access_token");
            this.refresh_token = (string)obj.SelectToken("refresh_token");
        }
        internal string error_msg { get; set; }
        internal string access_token { get; set; }
        internal string refresh_token { get; set; }
    }
    internal class Info
    {
        public Info(string resp)
        {
            JObject obj = JObject.Parse(resp);
            this.error_msg = (string)obj.SelectToken("error_msg");
            this.quota = (string)obj.SelectToken("quota");
            this.uesed = (string)obj.SelectToken("uesed");
        }
        internal string error_msg { get; set; }
        internal string quota { get; set; }
        internal string uesed { get; set; }
    }
    internal class Upload
    {
        public Upload(string resp)
        {
            JObject obj = JObject.Parse(resp);
            this.error_msg = (string)obj.SelectToken("error_msg");
            this.path = (string)obj.SelectToken("path");
            this.md5 = (string)obj.SelectToken("md5");
            this.size = (string)obj.SelectToken("size");
        }
        internal string error_msg { get; set; }
        internal string fs_id { get; set; }
        internal string path { get; set; }
        internal string ctime { get; set; }
        internal string mtime { get; set; }
        internal string md5 { get; set; }
        internal string size { get; set; }
        internal string request_id { get; set; }
    }
}
